﻿from sqlite import init_db, query_ignore_list, add_to_ignore_list, remove_from_ignore_list, query_sync_history
from flask import Flask, render_template, request, redirect, url_for
from config import ftp_connect
from path import MyPath
from apscheduler.schedulers.background import BackgroundScheduler
import os

app = Flask(__name__)
wsgi_app = app.wsgi_app


# 登录路由
@app.route('/login', methods=['GET', 'POST'])
def login_page():
    """
    处理登录页面的请求
    """
    if request.method == 'GET':
        return render_template('login.html')
    else:
        username = request.form.get("username")
        pwd = request.form.get("password")
        print(f"登录用户：{username}")
        print(f"登录密码：{pwd}")
        return login(username, pwd)


def login(username, password):
    """
    处理登录请求，判断用户名和密码是否匹配
    """
    if username == 'fanjiangnan' and password == '123456':
        return redirect('/')
    else:
        return redirect('/login')


@app.route('/', methods=['GET', 'POST'])
def ftp_file_sync():
    if request.method == 'GET':
        # 连接到ftp服务器
        ftp_conn = ftp_connect.connect_ftp()
        # 获取当前所在的云端路径
        cur_remote_path = ftp_connect.remote_path
        # 获取当前所在的本地路径
        cur_local_path = ftp_connect.local_path
        # 移动到目标文件夹
        ftp_conn.cwd(cur_remote_path)
        # ftp上的文件列表
        ftp_files = ftp_conn.nlst()
        # 需要返回给前端的字典，包含ftp文件名及其大小
        ftp_size_dict = {}
        # 需要返回给前端的文件同步状态字典
        ftp_state_dict = {}
        # ftp的忽略列表字典
        ftp_ignore_dict = {}
        # 本地文件列表
        local_files = os.listdir(ftp_connect.local_path)
        for file in ftp_conn.nlst():
            if file.find('.') == -1:
                ftp_size_dict.update({file: '文件夹'})
                ftp_state_dict.update({file: '文件夹无法判断同步状态'})
            else:
                is_ignore = query_ignore_list(file, cur_remote_path, cur_local_path)

                if not is_ignore:
                    ftp_ignore_dict.update({file: '忽略'})
                else:
                    ftp_ignore_dict.update({file: '不忽略'})
                ftp_size_dict.update({file: ftp_conn.size(file)})
                # 获取ftp上的文件大小
                try:
                    ftp_size = ftp_conn.size(cur_remote_path + '/' + file)
                except Exception as e:
                    ftp_size = -2
                    print(e)
                try:
                    local_size = os.path.getsize(cur_local_path + '\\' + file)
                except Exception as e:
                    local_size = -1
                    print(e)

                # 根据文件大小来判断是否同步
                if ftp_size == local_size:
                    ftp_state_dict.update({file: '已同步'})
                else:
                    ftp_state_dict.update({file: '未同步'})

        # 关闭ftp连接
        ftp_connect.close_ftp(ftp_conn)
        return render_template("home.html", ftp_files=ftp_files, ftp_size_dict=ftp_size_dict,
                               ftp_state_dict=ftp_state_dict, local_files=local_files, ftp_ignore_dict=ftp_ignore_dict)
    else:
        data = request.form.to_dict()
        MyPath.path += data.get('path')
        return redirect('/index')


@app.route('/index')
def next_page():
    # 连接到ftp服务器
    ftp_conn = ftp_connect.connect_ftp()
    # 获取当前所在的云端路径
    cur_remote_path = ftp_connect.remote_path + MyPath.path
    # 获取当前所在的本地路径
    cur_local_path = ftp_connect.local_path
    for i in MyPath.path:
        if i == '/':
            cur_local_path += '\\'
        else:
            cur_local_path += i
    # 移动到目标文件夹
    try:
        ftp_conn.cwd(cur_remote_path)
    except Exception as e:
        print(e)
    # ftp上的文件列表
    ftp_files = ftp_conn.nlst()
    # 需要返回给前端的字典，包含ftp文件名及其大小
    ftp_size_dict = {}
    # 需要返回给前端的文件同步状态字典
    ftp_state_dict = {}
    # ftp的忽略列表字典
    ftp_ignore_dict = {}
    for file in ftp_conn.nlst():
        if file.find('.') == -1:
            ftp_size_dict.update({file: '文件夹'})
            ftp_state_dict.update({file: '文件夹无法判断同步状态'})
        else:
            is_ignore = query_ignore_list(file, cur_remote_path, cur_local_path)
            if not is_ignore:
                ftp_ignore_dict.update({file: '忽略'})
            else:
                ftp_ignore_dict.update({file: '不忽略'})
            ftp_size_dict.update({file: ftp_conn.size(file)})
            # 获取ftp上的文件大小
            try:
                ftp_size = ftp_conn.size(cur_remote_path + '/' + file)
            except Exception as e:
                ftp_size = -2
                print(e)
            try:
                local_size = os.path.getsize(cur_local_path + '\\' + file)
            except Exception as e:
                local_size = -1
                print(e)
            # 根据文件大小来判断是否同步
            if ftp_size == local_size:
                ftp_state_dict.update({file: '已同步'})
            else:
                ftp_state_dict.update({file: '未同步'})

    # 关闭ftp连接
    ftp_connect.close_ftp(ftp_conn)
    return render_template("home.html", ftp_files=ftp_files, ftp_size_dict=ftp_size_dict,
                           ftp_state_dict=ftp_state_dict, ftp_ignore_dict=ftp_ignore_dict)


# 上传文件到目标文件夹
@app.route("/op/upload", methods=['POST'])
def upload_file_to_target_folder():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 移动到目标文件夹
    ftp.cwd('/home/ftproot/ftptest/hjs')
    # 将文件上传到ftp服务器
    ftp_connect.upload_ftp(ftp)
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)
    # 跳转到 hello 路由
    return redirect(url_for('hello'))


# 从目标文件夹下载文件
@app.route('/op/download', methods=['POST'])
def download_file_from_target_folder():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 移动到目标文件夹
    ftp.cwd('/home/ftproot/ftptest/hjs')
    # 从ftp服务器下载文件
    ftp_connect.download_ftp(ftp)
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)
    # 返回成功信息
    return '1'


# 与目标文件夹同步文件
@app.route('/op/sync', methods=['POST'])
def sync_files_with_target_folder():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 移动到目标文件夹
    ftp.cwd('/home/ftproot/ftptest/hjs')
    # 同步文件
    ftp_connect.sync_ftp(ftp)
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)
    # 返回成功信息
    return '1'


# 与目标文件夹进行本地同步
@app.route('/op/localSync', methods=['POST', 'GET'])
def local_sync_with_target_folder():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 获取当前的云路径
    current_path = ftp_connect.remote_path + MyPath.path
    # 获取当前的本地路径
    local_path = ftp_connect.local_path
    for i in MyPath.path:
        if i == '/':
            local_path += '\\'
        else:
            local_path += i
    # 移动到目标文件夹
    ftp.cwd(current_path)
    # 获取需要同步的文件名称
    data = request.form.to_dict().get('fileName')
    # 获取ftp上的文件大小
    try:
        ftp_size = ftp.size(current_path + '/' + data)
    except Exception as e:
        ftp_size = -2
        print(e)
    # 获取本地文件大小
    try:
        local_size = os.path.getsize(local_path + '\\' + data)
    except Exception as e:
        local_size = -1
        print(e)
    # 进行本地同步
    ftp_connect.local_sync(ftp, current_path, local_path, ftp_size, local_size, data)
    # 跳转到主页
    return redirect('/index')


# 与目标文件夹优先进行ftp同步
@app.route('/op/ftpSync', methods=['POST', 'GET'])
def ftp_sync_with_target_folder():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 获取当前的云路径
    current_path = ftp_connect.remote_path + MyPath.path
    # 获取当前的本地路径
    local_path = ftp_connect.local_path
    for i in MyPath.path:
        if i == '/':
            local_path += '\\'
        else:
            local_path += i
    # 移动到目标文件夹
    ftp.cwd(current_path)
    # 获取需要同步的文件名称
    data = request.form.to_dict().get('fileName')
    # 获取ftp上的文件大小
    try:
        ftp_size = ftp.size(current_path + '/' + data)
    except Exception as e:
        ftp_size = -2
        print(e)
    # 获取本地文件大小
    try:
        local_size = os.path.getsize(local_path + '\\' + data)
    except Exception as e:
        local_size = -1
        print(e)
    # 进行ftp同步
    ftp_connect.ftp_sync(ftp, current_path, local_path, ftp_size, local_size, data)
    # 跳转到主页
    return redirect('/index')


# 返回上一级文件夹
@app.route('/op/back', methods=['GET', 'POST'])
def go_back_to_previous_folder():
    print(MyPath.path, '当前地址')
    new_url = ''
    # 将当前路径转成列表，并倒序排列
    ls = list(MyPath.path)
    ls.reverse()
    flag = False
    for i in ls:
        if flag:
            new_url = i + new_url
        if i == '/':
            flag = True
    MyPath.path = new_url
    # 跳转到主页
    return redirect('/index')


# 从ftp中删除一个文件
@app.route('/op/delete', methods=['POST', 'GET'])
def delete_file_from_ftp():
    # 获取请求中的数据
    data = request.form.to_dict()
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 获取当前的云路径
    current_path = ftp_connect.remote_path + MyPath.path
    # 移动到目标文件夹
    ftp.cwd(current_path)
    print('删除路径:' + current_path + '/' + data.get('fileName'))
    # 判断是否为目录
    if data.get('isDir') == 'false':
        try:
            # 删除文件
            ftp.delete(current_path + '/' + data.get('fileName'))
        except Exception as e:
            print(e)
            return '400'
    else:
        try:
            # 删除目录
            ftp.rmd(current_path + '/' + data.get('fileName'))
        except Exception as e:
            print(e)
            return '400'
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)
    # 返回200表示删除成功
    return '200'


# 改变一个文件或文件夹的忽略状态
@app.route('/op/changeIgnore', methods=['POST', 'GET'])
def change_ignore_status():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 获取当前的云路径
    current_path = ftp_connect.remote_path + MyPath.path
    # 获取当前的本地路径
    local_path = ftp_connect.local_path
    for i in MyPath.path:
        if i == '/':
            local_path += '\\'
        else:
            local_path += i
    # 移动到目标文件夹
    ftp.cwd(current_path)
    # 获取请求中的数据
    data = request.form.to_dict()
    # 如果状态为"忽略"
    if data.get('currentState') == '忽略':
        # 将目标文件或文件夹添加到忽略列表
        add_to_ignore_list(data.get('filename'), current_path, local_path)
    else:
        # 将目标文件或文件夹从忽略列表移除
        remove_from_ignore_list(data.get('filename'), current_path, local_path)
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)
    # 返回1表示执行成功
    return '1'


# 查看历史记录
@app.route('/history')
def view_history_records():
    # 查询同步历史记录
    history_records = query_sync_history()
    # 初始化结果列表
    result = []
    for record in history_records:
        # 将记录内容拼接成字符串
        formatted_record = '名称: ' + record[0] + " " + "操作: " + record[1] + " " + "时间: " + record[2]
        # 添加到结果列表中
        result.append(formatted_record)

    # 使用模板渲染HTML页面，并将结果传递给模板
    return render_template('historic_records.html', result=result)


# 定时扫描目标文件夹
def schedule_folder_scan():
    # 连接到ftp服务器
    ftp = ftp_connect.connect_ftp()
    # 获取当前的云路径
    current_path = ftp_connect.remote_path + MyPath.path
    # 获取当前的本地路径
    local_path = ftp_connect.local_path
    for i in MyPath.path:
        if i == '/':
            local_path += '\\'
        else:
            local_path += i
    # 移动到目标文件夹
    ftp.cwd(current_path)
    # 获取本地文件夹列表
    items = os.listdir(local_path)
    for data in items:
        if os.path.isdir(local_path + '\\' + data):
            continue
        # 获取ftp上的文件大小
        try:
            ftp_size = ftp.size(current_path + '/' + data)
        except Exception as e:
            ftp_size = -2
            print(e)
        # 获取本地文件大小
        try:
            local_size = os.path.getsize(local_path + '\\' + data)
        except Exception as e:
            local_size = -1
            print(e)
        # 本地为主的同步
        ftp_connect.local_sync(ftp, current_path, local_path, ftp_size, local_size, data)
    # 关闭ftp连接
    ftp_connect.close_ftp(ftp)


# 创建后台调度器
scheduler = BackgroundScheduler()
# 每分钟执行一次目标文件夹扫描
scheduler.add_job(func=schedule_folder_scan, trigger='interval', minutes=1)
# 启动调度器
scheduler.start()


if __name__ == '__main__':
    init_db()
    # 从环境变量中获取主机名
    HOST = os.environ.get('SERVER_HOST', 'localhost')
    try:
        # 从环境变量中获取端口号
        PORT = int(os.environ.get('SERVER_PORT', '5555'))
    except ValueError:
        # 如果端口号无效，默认为5555
        PORT = 5555
    # 运行应用程序（启动web服务器）
    app.run(HOST, PORT, debug=True)
